package com.xyzk.diagnose.tools;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;

import org.ini4j.Ini;
import org.ini4j.InvalidFileFormatException;
import org.ini4j.Profile.Section;

import com.xyzk.diagnose.R;
import com.xyzk.diagnose.entity.Can;
import com.xyzk.diagnose.entity.Cartype;
import com.xyzk.diagnose.view.CToast;

public class FileReader {
	private static Cartype cartype = Cartype.getInstance();

	/**
	 *
	 * @param  path 文件路径
	 * @param  name 读取的section名字
	 * @return 返回section对象
	 */
	public static Section readSectionForIni(String path, String name){
		try {
			return new Ini(new File(path)).get(name);
		} catch (InvalidFileFormatException e) {
			printStackTrace(e, R.string.Dialog_file_content_error);
		} catch (IOException e) {
			printStackTrace(e, R.string.Dialog_file_path_error);
		}
		return null;
	}

	/**
	 * 读取标准列表
	 * @param  path 文件路径
	 * @param  name 读取的section名字
	 * @return 读取到的列表
	 */
	public static ArrayList<String> readList(String path, String name){
		ArrayList<String> list = new ArrayList<String>();
		try {
			Ini inifile = new Ini(new File(path));
			Section sec = inifile.get(name);
			if(sec != null ){
				for(int i = 0; i < Integer.valueOf(sec.get("NUM")); i++){
					list.add(sec.get("T" + i));
				}
			}
		} catch (InvalidFileFormatException e) {
			printStackTrace(e, R.string.Dialog_file_content_error);
		} catch (IOException e) {
			printStackTrace(e, R.string.Dialog_file_path_error);
		}
		return list;
	}

	/**
	 * 读取config.ini
	 * @param
	 */
	public static void readConfig(){
		try {
			Ini inifile = new Ini(new File(Common.GUEST + "config.ini"));
			Section sec = inifile.get("SETTING");
			Common.serverIP = sec.get("ServerIP");
//			Common.printNum = Integer.valueOf(sec.get("PrintNum"));
			//存入缓存，不再使用
			Common.mes_ip = sec.get("MesServerIP");
			Common.mes_ver = sec.get("MesServerIP_Version");
			Common.mes_esc = sec.get("MesServerIP_EPB");
			Common.mes_obd = sec.get("MesServerIP_OBD");
			Common.mes_obd2 = sec.get("UpOBD2");
			String v_en = sec.get("UpOBD2_ENABLE");
			Common.mes_ems=sec.get("ECU_SERVER");
			if(v_en != null && v_en.length() > 0)
				Common.mes_obd2_en = Integer.valueOf(v_en);

			// 读取文件上传的配置文件信息
			String v_webenable = sec.get("WEB_ENABLE");
			if("1".equals(v_webenable))
				Common.web_enable= true;
			else
				Common.web_enable= false;
			Common.web_API_SelectUpdate = sec.get("WEB1");
			Common.web_API_AppUpdate = sec.get("WEB2");
			Common.web_updata = sec.get("WEB3");
			Common.web_API_File = sec.get("WEB4");
			Common.web_API_AppStatus = sec.get("WEB5");
			Common.web_API_SelectPinforVin=sec.get("WEB6");
			Common.web_API_SelectHeat=sec.get("WEB7");
			Common.web_GetTPMS = sec.get("web_GetTPMS");
			sec = inifile.get("STATION");
			cartype.clearStationsList();//先清除数据
			for(int i = 0; i <Integer.valueOf(sec.get("NUM")); i++)
			{
				cartype.setStationsList(sec.get("T" + i));
			}

		} catch (InvalidFileFormatException e) {
			printStackTrace(e, R.string.Dialog_file_content_error);
		} catch (IOException e) {
			printStackTrace(e, R.string.Dialog_file_path_error);
		}
	}



	/**
	 * 读取can.ini
	 * @param path 文件路径
	 * @param module 模块名称
	 * @param args 如果有参数表示是扩展帧，没有参数则是正常诊断
	 */
	public static void readCan(String path, String module, String... args){
		try {
			Ini inican = new Ini(new File(path));
			int mode = 1;
			Section sec = inican.get(module);
			if(sec == null) return;
			if(sec.get("CAN").equals("PCAN") || sec.get("CAN").equals("P_EXTED")){
				if("0".equals(Commonfunc.getSharedPreference(Common.CAN, "0"))){
					mode = 1;
				}else{
					mode = 2;
				}
			}else if(sec.get("CAN").equals("BCAN") || sec.get("CAN").equals("B_EXTED")){
				if("0".equals(Commonfunc.getSharedPreference(Common.CAN, "0"))){
					mode = 2;
				}else{
					mode = 1;
				}
			}else{
				mode = 3;
			}
			int baud = Integer.valueOf(sec.get("BAUD"));
			byte [] addr = new byte[8];
			if(args.length > 0){//扩展帧
				int id = Commonfunc.hexStringtoInt(sec.get("ID_SEND"));
				addr[0] = (byte) ((id / 0x1000000) & 0xFF);
				addr[1] = (byte) ((id / 0x10000) & 0xFF);
				addr[2] = (byte) ((id / 0x100) & 0xFF);
				addr[3] = (byte) (id & 0xFF);
				id = Commonfunc.hexStringtoInt(sec.get("ID_RECV"));
				addr[4] = (byte) ((id / 0x1000000) & 0xFF);
				addr[5] = (byte) ((id / 0x10000) & 0xFF);
				addr[6] = (byte) ((id / 0x100) & 0xFF);
				addr[7] = (byte) (id & 0xFF);
			}else{
				int id = Commonfunc.hexStringtoInt(sec.get("ID_SEND"));
				addr[0] = (byte) ((id / 0x100) & 0xFF);
				addr[1] = (byte) (id & 0xFF);
				id = Commonfunc.hexStringtoInt(sec.get("ID_RECV"));
				addr[2] = (byte) ((id / 0x100) & 0xFF);
				addr[3] = (byte) (id & 0xFF);
			}
			//存入对象,只需读一次
			cartype.setCan(module, new Can(mode, baud, addr));
		}catch (InvalidFileFormatException e) {
			printStackTrace(e, R.string.Dialog_file_content_error);
		} catch (IOException e) {
			printStackTrace(e, R.string.Dialog_file_path_error);
		}
	}

	/**
	 * 读取writedata.ini
	 * @param  path 文件路径
	 */
	public static void readWriteData(String path){
		try {
			Ini inifile = new Ini(new File(path));
			String[] configNames = inifile.get("CONFIG", "MODULE").split(",");
			for(int i = 0; i < configNames.length; i++){
				Section sec = inifile.get(configNames[i]);
				int len = Integer.valueOf(sec.get("LEN"));
				byte [] config = new byte[len];
				Commonfunc.cmdStringToBytes(sec.get(cartype.cartype), config);
				cartype.setWriteByte(configNames[i], config);
			}
		}catch (InvalidFileFormatException e) {
			printStackTrace(e, R.string.Dialog_file_content_error);
		} catch (IOException e) {
			printStackTrace(e, R.string.Dialog_file_path_error);
		}
	}

	/**
	 * 读取dtc.ini
	 * @param module
	 * @param cmd
	 * @param dtcLen 故障码的长度2或三个字节
	 * @return
	 */
	public static ArrayList<HashMap<String,String>>  readDtc(String module, byte[] cmd, int dtcLen){
		ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>();
		try {
			String path = cartype.carDirectory + "dtc.ini";
			Ini inidtc = new Ini(new File(path));
			Section sec = inidtc.get(module);
			Section secFilter = inidtc.get(module + "_FILTER");
			ArrayList<String> filterListName = new ArrayList<String>();
			if(secFilter != null){
				int filterNum = Integer.valueOf(secFilter.get("NUM"));//过滤的故障码个数
				if(filterNum > 0){
					for(int i = 0; i < filterNum; i ++){
						String data = secFilter.get("T" + (i + 1));
						filterListName.add(data);
					}
				}
			}
			byte[] code = new byte[3];
			boolean filter = false;
			for(int i = 0; i < (cmd[0]&0xFF); i ++){
				System.arraycopy(cmd, 1 + i * 4, code, 0, 3);
				String pcode = Commonfunc.getPUBCCode(code, dtcLen);
				for(int k = 0; k < filterListName.size(); k ++){
					if(pcode.equals(filterListName.get(k))){
						filter = true;
						break;
					}
				}
				if(filter) continue;
				HashMap<String,String> map = new HashMap<String, String>();
				String dtc;
				if(sec == null){
					dtc = "ID未定义";
				}else{
					dtc = sec.get(pcode);
					if(dtc == null || dtc.length()== 0){
						dtc = "ID未定义";
					}
				}
				map.put(Common.CONTENT, pcode + "--" + dtc);
				list.add(map);
			}
		} catch (InvalidFileFormatException e) {
			printStackTrace(e, R.string.Dialog_file_content_error);
		} catch (IOException e) {
			printStackTrace(e, R.string.Dialog_file_path_error);
		}
		return list;
	}

	/**
	 * 读取dtc.ini
	 * @param module
	 * @param dtcs
	 * @param dtcLen 故障码的长度2或三个字节
	 * @param isShort 单个故障码定义的长度是3或4个字节
	 * @param isFilter 是否过滤
	 * @return
	 */
	public static ArrayList<HashMap<String,String>>  readDtc(String module,byte[] dtcs,int dtcLen, boolean isShort, boolean isFilter){
		ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>();
		try {
			String path = cartype.carDirectory + "dtc.ini";
			Ini inidtc = new Ini(new File(path));
			Section sec = inidtc.get(module);
			Section secFilter = inidtc.get(module + "_FILTER");
			ArrayList<String> filterListName = new ArrayList<String>();
			if(secFilter != null){
				int filterNum = Integer.valueOf(secFilter.get("NUM"));//过滤的故障码个数
				if(filterNum > 0){
					for(int i = 0; i < filterNum; i ++){
						String data = secFilter.get("T" + (i + 1));
						filterListName.add(data);
					}
				}
			}
			byte[] code = new byte[3];
			boolean filter = false;
			for(int i = 0; i < (dtcs[0]&0xFF); i ++){
				String pcode;
				if(isShort){
					if(isFilter && (dtcs[(i+1)*3] & 0x60) != 0x60){
						continue;
					}
					System.arraycopy(dtcs, 1 + i * 3, code, 0, 2);
					pcode = Commonfunc.getPUBCCode(code, 2);
				}else{
					if(isFilter && (dtcs[(i+1)*4] & 0x09) != 0x09){
						continue;
					}
					System.arraycopy(dtcs, 1 + i * 4, code, 0, 3);
					if (((dtcs[(i+1)*4]>>0) & 0x01)!=0x01){
						continue;
					}
					if ((cartype.car.equals("T1PPHEV")&&((dtcs[(i+1)*4]>>0) & 0x01)!=0x01&&((dtcs[(i+1)*4]>>3) & 0x01)!=0x01&&!(module.equals("EMS")||module.equals("HCU")||module.equals("BMS")))
					||(cartype.car.equals("T1PPHEV")&&module.equals("EMS")&&((dtcs[(i+1)*4]>>0) & 0x01)!=0x01&&((dtcs[(i+1)*4]>>4) & 0x01)!=0x00)
					||(cartype.car.equals("T1PPHEV")&&(module.equals("HCU")||module.equals("BMS"))&&((dtcs[(i+1)*4]>>0) & 0x01)!=0x01)){
						continue;
					}
					pcode = Commonfunc.getPUBCCode(code, dtcLen);
				}
				for(int k = 0; k < filterListName.size(); k ++){
					if(pcode.equals(filterListName.get(k))){
						filter = true;
						break;
					}
				}
//				if (dtcs[i+1])
				if(filter) continue;
				HashMap<String,String> map = new HashMap<String, String>();
				String dtc;
				if(sec == null){
					dtc = "ID未定义";
				}else{
					dtc = sec.get(pcode);
					if(dtc == null || dtc.length()== 0){
						dtc = "ID未定义";
					}
				}
				map.put(Common.CONTENT, pcode + "--" + dtc);
				list.add(map);
			}
		} catch (InvalidFileFormatException e) {
			printStackTrace(e, R.string.Dialog_file_content_error);
		} catch (IOException e) {
			printStackTrace(e, R.string.Dialog_file_path_error);
		}
		return list;
	}

	/**
	 * 读取dtc.ini
	 * @param module
	 * @param cmd
	 * @param dtcLen 故障码的长度2或三个字节
	 * @param
	 * @param
	 * @return
	 */
	public static ArrayList<HashMap<String,String>>  readEmsDtc(String module,byte[] cmd,int dtcLen){
		ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>();
		try {
			String path = cartype.carDirectory + "dtc.ini";
			Ini inidtc = new Ini(new File(path));
			Section sec = inidtc.get(module);
			Section secFilter = inidtc.get(module + "_FILTER");
			int filterNum = Integer.valueOf(secFilter.get("NUM"));//过滤的故障码个数
			ArrayList<String> filterListName = new ArrayList<String>();
			if(filterNum > 0){
				for(int i = 0; i < filterNum; i ++){
					String data = secFilter.get("T" + (i + 1));
					filterListName.add(data);
				}
			}
			byte[] code = new byte[3];
			boolean filter = false;
			for(int i = 0; i < (cmd[0]&0xFF); i ++){
				String pcode;
				if((cmd[(i+1)*4] & 0x11) != 0x01){
					continue;
				}
				System.arraycopy(cmd, 1 + i * 4, code, 0, 3);
				pcode = Commonfunc.getPUBCCode(code, dtcLen);
				for(int k = 0; k < filterListName.size(); k ++){
					if(pcode.equals(filterListName.get(k))){
						filter = true;
						break;
					}
				}
				if(!filter){
					HashMap<String,String> map = new HashMap<String, String>();
					String dtc = sec.get(pcode);
					if(dtc == null || dtc.length()== 0){
						dtc = "ID未定义";
					}
					map.put(Common.CONTENT, pcode + "--" + dtc);
					list.add(map);
				}
			}
		} catch (InvalidFileFormatException e) {
			printStackTrace(e, R.string.Dialog_file_content_error);
		} catch (IOException e) {
			printStackTrace(e, R.string.Dialog_file_path_error);
		}
		return list;
	}

	/**
	 * 读取Step文件
	 * @param
	 * @param  path 文件路径
	 */
	public static void readStep(String path){
		try {
			Ini inifile = new Ini(new File(path));
			//获取头部信息
			Section sec = inifile.get("STEP");
			cartype.setMap("AUTO", Integer.valueOf(sec.get("AUTO")));
			int num = Integer.valueOf(sec.get("NUM"));
			//先清除数据
			cartype.clearModuleList();
			for(int i = 0; i <num; i ++){
				String step_name = sec.get("T" + i);
				String mode = step_name.substring(0, 3);
				String name = step_name.substring(4, step_name.length());
				if("OPT".equals(mode)){
					if(cartype.getMap(name) > 0){
						cartype.setModuleListFilter(name);
						cartype.setModuleList(name);
					}
				}else if("REQ".equals(mode)){
					cartype.setModuleListFilter(name);
					cartype.setModuleList(name);
				}else if("SHW".equals(mode)){
					cartype.setModuleList(step_name);
				}
			}
		}catch (InvalidFileFormatException e) {
			printStackTrace(e, R.string.Dialog_file_content_error);
		} catch (IOException e) {
			printStackTrace(e, R.string.Dialog_file_path_error);
		}
	}

	/**
	 * 提示文件异常
	 * @param e
	 * @param resid 提示字符串资源id
	 */
	private static void printStackTrace(Exception e, int resid){
		e.printStackTrace();
		CToast.show(resid);
	}
	/**
	 *  读取并解析hex文件
	 * @paramPadrbuf,4byte-文件总长度;2byte-文件段数;[4byte-起始地址;4byte-长度信息],[4byte-起始地址;4byte-长度信息]....
	 */
	@SuppressWarnings("resource")
	public static byte [] FileReadHexFile(String HexFile,byte [] Padrbuf) throws FileNotFoundException,IOException
	{
		byte [] readbuf =  null;
		File file = new File(HexFile);
		if (!file.exists() || !file.isFile()) {
			return readbuf;
		}
		long filelength = file.length();
		if(filelength > 10) //ok
			readbuf = new byte[(int) (filelength / 2)];
		FileInputStream fileInputStream = new FileInputStream(file);
		InputStreamReader inputreader = new InputStreamReader(fileInputStream);
		BufferedReader buffreader = new BufferedReader(inputreader);
		String line = "";
		int len = 0;
		int readlen = 0;
		short v_black = 0;
		int v_black_adr = 0;
		int v_black_len = 0;
		int v_adr = 0;
		//boolean isstart = false;
		byte [] v_adbyte = new byte[4];
		byte [] v_buf = new byte[64];
		while ((line = buffreader.readLine()) != null)
		{
			//解析数据
			if(line.length() > 0)
			{
				v_adbyte.clone();
				len = ReadHexLine(line, v_adbyte,v_buf);
				if(len > 0 && len < 100) //数据
				{
					if(v_black < 1) break;
					v_adr = ((v_adbyte[0]&0xFF) << 8) + (v_adbyte[1]&0xFF);
					if(v_adr != ((v_black_len + v_black_adr)&0xFFFF)) //地址不连续,开启新地址
					{
						v_black_adr += v_adr;
						if(v_black_len > 0) //没数据,直接改地址
						{
							//记录首地址
							CopyIntToBytes(v_black_adr,Padrbuf, 6 + v_black * 8,4);
							//System.arraycopy(intToBytes(v_black_adr), 0, Padrbuf, 6 + v_black * 8, 4);
							//记录前面一块长度信息
							CopyIntToBytes(v_black_len,Padrbuf,10 + (v_black - 1) * 8,4);
							//System.arraycopy(intToBytes(v_black_len), 0, Padrbuf, 10 + (v_black - 1) * 8, 4);
							v_black ++;
							v_black_adr +=v_adr;
							v_black_len = 0;
						}
						else
						{
							//记录首地址变更
							CopyIntToBytes(v_black_adr,Padrbuf,6 + (v_black - 1) * 8,4);
							//System.arraycopy(intToBytes(v_black_adr), 0, Padrbuf, 6 + (v_black - 1) * 8, 4);
						}
					}
					v_black_len += len;
					System.arraycopy(v_buf, 0, readbuf,readlen, len);
					readlen += len;
				}
				else if(len == 1000) //新起一段
				{
					v_adr =  ((v_adbyte[0]&0xFF) << 24) + ((v_adbyte[1]&0xFF) << 16);
					if((v_black_adr + v_black_len <  v_adr) || (v_black == 0))
					{
						v_black_adr = v_adr;
						//System.arraycopy(v_adbyte, 0, v_buf, 6, 2);
						if(v_black_len > 0)
						{
							//记录首地址
							CopyIntToBytes(v_black_adr,Padrbuf, 6 + v_black * 8,4);
							//记录前面一块长度信息
							CopyIntToBytes(v_black_len,Padrbuf,10 + (v_black - 1) * 8,4);
							//System.arraycopy(intToBytes(v_black_len), 0, Padrbuf, 10 + (v_black - 1) * 8, 4);
							v_black ++;
							v_black_len = 0;
						}
						else
						{
							//记录首地址
							if(v_black == 0)
							{
								v_black ++;
							}
							CopyIntToBytes(v_black_adr,Padrbuf,6 + (v_black - 1) * 8,4);
						}
					}
					else if(v_black_len == 0)//遇到空地址
					{
						v_black_adr = v_adr;
						CopyIntToBytes(v_black_adr,Padrbuf,6 + (v_black - 1) * 8,4);
					}
				}
				else
					break;
			}
		}
		//记录最后一块数据长度
		if(v_black > 0)
		{
			//记录前面一块长度信息
			CopyIntToBytes(v_black_len,Padrbuf,10 + (v_black - 1) * 8,4);
			//System.arraycopy(intToBytes(v_black_len), 0, Padrbuf, 10 + (v_black - 1) * 8, 4);
		}
		//记录总长度
		CopyIntToBytes(readlen,Padrbuf,0,4);
		//记录块数量
		CopyIntToBytes(v_black,Padrbuf,4,2);
		//System.arraycopy(intToBytes(v_black), 0, Padrbuf, 4, 2);
		return readbuf;
	}
	//返回 0--结束,1000-头地址,1- 100实际数据长度
	static int ReadHexLine(String Pline,byte [] Padr,byte [] Pdata)
	{
		int error = 0;
		int len = 0;
		String head = Pline.substring(0,3);
		Pline = Pline.substring(3);
		byte [] v_buf = new byte[64];
		if(head.equals(":02")) //头
		{
			len = StringToBytes(Pline, v_buf, v_buf.length);
			if(len < 4) return 0;
			System.arraycopy(v_buf, 3, Padr, 0,2);
			error = 1000;
		}
		else if(head.equals(":00")) //结束
		{
			error = 0;
		}
		else
		{
			int buflen = HexStringtoInt(head.substring(1));
			len = StringToBytes(Pline, v_buf, v_buf.length);
			if(len < 4) return 0;
			if((buflen + 4) == len) //ok
			{
				error = buflen;
				//copy
				System.arraycopy(v_buf, 0, Padr, 0,2);  //address
				if(Pdata != null)
					System.arraycopy(v_buf, 3, Pdata, 0,buflen);	//data
			}
			else
				error = 0;
		}
		return error;
	}
	public static int StringToBytes(String str,byte[] buf,int cmdlen)
	{
		int len = 0;
		int strlen = str.length();
		for(int i = 0; i < cmdlen; i ++)
		{
			String data = "";
			if(strlen >= (i* 2 + 2))
				data = str.substring(i * 2, i * 2 + 2);
			else
				break;
			//if(Common.Debug) Log.i(TAG,"data:"+ data);
			buf[i] = (byte) HexStringtoInt(data);
			len ++;
		}
		//if(Common.Debug) Log.i(TAG,"Obj:"+ bytesToHexString(buf, 0,cmdlen));
		return len;
	}
	public static int HexStringtoInt(String hexstr)
	{
		int x=0,iRet = 0;
		if(hexstr == null)
			return iRet;
		int length = hexstr.length();
		for(int i = 0; i < length; i ++)
		{
			char c = hexstr.charAt(i);
			//对'0'->0，'a'->10
			if(c>='a'&&c<='f'){
				x=c-'a'+10;
			}else if(c>='A'&&c<='F'){
				x=c-'A'+10;
			}else if(c>='0'&&c<='9'){
				x=c-'0';
			}
			iRet=(iRet<<4)| x;//n=n*4+x,移位拼接
		}
		return iRet;
	}
	public static void CopyIntToBytes(int P,byte [] Pbuf,int start,int Plen)
	{
		for(int k = 0;k < Plen; k ++ )
		{
			Pbuf[k + start] = (byte) ((P >> ((Plen - k - 1) * 8)&0xFF));
		}
	}
	/**
	 * 读取并解析hex文件
	 * 返回值,2byte-文件总长度,后面数据
	 */
	public static byte [] FileReadRsaFile(String RsaFile) throws FileNotFoundException,IOException
	{
		byte [] readbuf =  null;
		File file = new File(RsaFile);
		if (!file.exists() || !file.isFile()) {
			return readbuf;
		}
		long filelength = file.length();
		if(filelength > 10) //ok
			readbuf = new byte[(int) ((filelength + 20) / 6)];
		byte [] v_read = new byte[(int) (filelength + 2)];
		FileInputStream fileInputStream = new FileInputStream(file);
		int v_readlen = fileInputStream.read(v_read);
		String v_readstr = new String(v_read);
		String st = "";
		int v_adr = 0;
		int rsa_data = 0;
		//解析数据
		while(true)
		{
			v_adr = v_readstr.indexOf("0x");
			if(v_adr >= 0)
			{
				st = v_readstr.substring(v_adr + 2, v_adr + 4);
				v_readstr = v_readstr.substring(v_adr + 4);
				if(st.length() == 2)
					readbuf[2 + rsa_data ++] = (byte) HexStringtoInt(st);
				else
					break;
			}
			else
				break;
		}
		//记录长度
		CopyIntToBytes(rsa_data,readbuf,0,2);
		return readbuf;
	}
}
